package com.gopay.bis.service.bank.impl.expay;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.common.util.constants.BisPayConstants;
import com.gopay.bis.manager.bank.expay.IcbcExPayManager;
import com.gopay.bis.service.bank.BisExpayDtlService;
import com.gopay.bis.service.bank.sms.SmsSupportController;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.IcbcConstants;
import com.gopay.common.constants.bank.IcbcExpayConstants;
import com.gopay.common.constants.bank.SmsAuthMarkConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.constants.trans.GatewaySource;
import com.gopay.common.constants.txncd.IntTxnCd;
import com.gopay.common.cps.manager.order.CpsGeneralMainOrderQueryManager;
import com.gopay.common.domain.bank.BisBankExpayDtl;
import com.gopay.common.domain.bank.ExPayBaseMessage;
import com.gopay.common.domain.bank.icbc.expay.pay.req.IcbcExpayCmsReq;
import com.gopay.common.domain.bank.icbc.expay.pay.res.IcbcExpayCmsRes;
import com.gopay.common.domain.bank.icbc.expay.prepay.res.IcbcPreExpayCmsRes;
import com.gopay.common.domain.bank.icbc.expay.query.req.IcbcQueryExpayCmsReq;
import com.gopay.common.domain.bank.icbc.expay.query.res.IcbcQueryExpayCmsRes;
import com.gopay.common.domain.bank.pab.expay.PabExPayMessage;
import com.gopay.common.domain.bank.pab.expay.res.PabExPayFastpayFPARes;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.TransUtil;
import com.gopay.remote.bank.BisCertificationRemoteService;
import com.gopay.remote.bank.ExPayInteractRemoteService;

/** 
 * 工行快捷支付实现类
 * @ClassName: IcbcExPayServiceImpl 
 * @author w_jiqing 
 * @date 2017年6月26日 上午11:37:38  
 */ 
public class IcbcExPayServiceImpl implements ExPayInteractRemoteService{
    
    private static Logger logger = LoggerFactory.getLogger(IcbcExPayServiceImpl.class);
    
    @Resource(name = "bisExpayDtlService")
    private BisExpayDtlService bisExpayDtlService;
    
    @Resource(name ="icbcExPayManager")
    private IcbcExPayManager icbcExPayManager;
    
    @Resource(name ="bisCertificationService")
    private BisCertificationRemoteService bisCertificationService;
    
    @Resource(name = "cpsGeneralMainOrderQueryManager")
    private CpsGeneralMainOrderQueryManager mainOrderQuery;
    
    /**
     * 发送短信，验证短信操作对象
     * 
     */
    private SmsSupportController smsController;

    
    @Override
    public Result certification(ExPayBaseMessage baseMsg) {
    	Result result = new Result(false);
        PabExPayMessage message = new PabExPayMessage();
        BeanUtils.copyProperties(baseMsg, message);
        try {
	        Map<String, String> param = new HashMap<String, String>();
	        Result res = (Result) bisCertificationService.cardCertification(message);
			   if(res.isSuccess()){
				   if((boolean)res.getModel("flag")){
					   // 成功处理
						result.setModel("flag", true);
						result.setModel("retMsg", res.getModel("retMsg"));
				   } else {
					   result.setModel("flag", false);
					   result.setModel("retMsg", res.getModel("retMsg"));
				   }
			   } else {
				    //验签失败
					param.put("returnMessage", "银行验签失败");
					
					result.setModel("flag", false);
					result.setErrorMsg("验签失败！");
			   }
		       result.setSuccess(true);
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6076);
        }
       return result;
    }

    @Override
    public Result sendSms(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        String oriOrderId = baseMsg.getOrderId();
        try {
            Map<String, String> smsRes = smsController.querySendSMS(baseMsg);
            if("00".equals(smsRes.get("flag"))){
                List<BisBankExpayDtl> list= bisExpayDtlService.getBisBankExpayDtlListbyElements(baseMsg, SmsAuthMarkConstants.APPLY_MARK_SUCCESS);
                if(list !=null && list.size()>0){
                    logger.error("工行快捷订单："+baseMsg.getOrderId()+",调用验证码重发接口。");
                    //已发送验证码，调用支付提交接口，不上传验证码
                    IcbcExpayCmsRes res= (IcbcExpayCmsRes) icbcExPayManager.payment(baseMsg, false);
                    if(res != null && "7".equals(res.getEb().getOut().getResult())){
                        // 银行发送短信成功 插入一条发送短信记录
                        smsRes = smsController.buildSendLog(baseMsg, Integer.valueOf(smsRes.get("sendCount")));
                        result.setModel("flag", true);
                    }else{
                        result.setModel("flag", false);
                        smsRes.put("resCode", ProcCodeConstants.PROC_CODE_100E6110);
                        smsRes.put("sendCount", Integer.valueOf(smsRes.get("sendCount")) + 1 + "");
                        smsRes.put("retMsg", "短信发送失败，请联系发卡行");
                    }
                    result.setModel("sendCount", smsRes.get("sendCount"));
                    result.setModel("retMsg", smsRes.get("retMsg"));
                    result.setModel("resCode", smsRes.get("resCode"));
                    result.setResultCode(smsRes.get("resCode"));
                }else{
                    //首次调用发短信
                    logger.error("工行快捷订单："+baseMsg.getOrderId()+",首次调用验证码获取接口。");
                    IcbcPreExpayCmsRes res= (IcbcPreExpayCmsRes) icbcExPayManager.sendSms(baseMsg);
                    if(res != null && "1".equals(res.getEb().getOut().getResult())){
                        //1：已向客户发送动态密码
                        // 银行发送短信成功 插入一条发送短信记录
                        baseMsg.setBankOrderId(res.getEb().getOut().getPaySerialNo());
                        smsRes = smsController.buildSendLog(baseMsg, Integer.valueOf(smsRes.get("sendCount")));
                        result.setModel("flag", true);
                    }else{
                        result.setModel("flag", false);
                        smsRes.put("resCode", ProcCodeConstants.PROC_CODE_100E6110);
                        smsRes.put("sendCount", Integer.valueOf(smsRes.get("sendCount")) + 1 + "");
                        smsRes.put("retMsg", "短信发送失败，请联系发卡行");
                    }
                    result.setModel("sendCount", smsRes.get("sendCount"));
                    result.setModel("retMsg", smsRes.get("retMsg"));
                    result.setModel("resCode", smsRes.get("resCode"));
                    result.setResultCode(smsRes.get("resCode"));
                }               
            }else{
                result.setModel("flag", false);
                result.setModel("retMsg", smsRes.get("retMsg"));
                result.setModel("resCode", smsRes.get("resCode"));
                result.setResultCode(smsRes.get("resCode"));
            }
            result.setSuccess(true);
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6077);
        }
        return result;
    }

    @Override
    public Result checkSms(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        try {
            Map<String, String> smsRes = smsController.queryCheckSMS(baseMsg);
            if("00".equals(smsRes.get("flag"))){
                result.setModel("flag", true);  
                smsRes.put("retMsg", "短信验证码输入正确");
                smsRes.put("resCode",ProcCodeConstants.PROC_CODE_100E6091);
            }else{
             // 验证失败
                result.setModel("flag", false);
                result.setModel("retMsg", "短信验证码错误，您还有" + (baseMsg.getFailMaxCount() - Integer.parseInt(smsRes.get("failCount")) - 1) + "次机会");
                result.setModel("resCode", ProcCodeConstants.PROC_CODE_100E6098);
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E6098);
                if(!ProcCodeConstants.PROC_CODE_100E6099.equals(smsRes.get("resCode"))){
                    Map<String, String> freezeRes = smsController.freezeCard(baseMsg);
                    if(freezeRes != null)
                        smsRes = freezeRes;
                }
            }
            result.setModel("failCount", smsRes.get("failCount"));
            result.setModel("retMsg", smsRes.get("retMsg"));
            result.setModel("resCode", smsRes.get("resCode"));
            result.setResultCode(smsRes.get("resCode"));     
            result.setSuccess(true);
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6078);
        }
        return result;
    }
    
    @Override
    public Result payment(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        CpsGenMainOrder cpsOrder =mainOrderQuery.get(baseMsg.getOrderId());
        // 钱包充值交易，鉴权，发短信，验短信和支付时上送的订单号不一致，银行订单号取之前关联的订单号
        if (IntTxnCd._00500.value.equals(cpsOrder.getGopayIntTxnCd())
                && GatewaySource.GATEWAY_SOURCE_05.value.equals(cpsOrder.getGatewaySource())
                && StringUtils.isNotBlank(cpsOrder.getRelevanceGopayOrderId())) {
        	
        	baseMsg.setBankOrderId(cpsOrder.getRelevanceGopayOrderId());
        } else if (IntTxnCd._01732.value.equals(cpsOrder.getGopayIntTxnCd())) {
        	
        	baseMsg.setBankOrderId(cpsOrder.getRelevanceGopayOrderId());
        } else{
        	baseMsg.setBankOrderId(baseMsg.getOrderId());
        }
        
        try {
            IcbcExpayCmsRes res =  (IcbcExpayCmsRes) icbcExPayManager.payment(baseMsg,true);
            result.setModel("res", res);
            result.setDefaultModel(true);
            Map<String, String> param = new HashMap<String, String>();
            if (res!= null && res.getEb().getOut().getResult()!=null &&"1".equals(res.getEb().getOut().getResult())) {
                // 验签成功&&交易成功
                param.put("orderId", baseMsg.getOrderId());
                param.put("amt", TransUtil.amountConvert2Yuan(res.getEb().getOut().getOrderAmt()));
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "00");
                param.put("retCode", "00");
                param.put("retMsg", "验签成功");
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(true);
            }else if(res!= null && res.getEb().getOut().getResult()!=null &&"2".equals(res.getEb().getOut().getResult())){
            	// 验签成功&&交易失败
            	param.put("orderId", baseMsg.getOrderId());
                param.put("amt", TransUtil.amountConvert2Yuan(res.getEb().getOut().getOrderAmt()));
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "01");
                param.put("retCode", "01");
                //参照银行提供文档，如果返回失败状态，信息及错误码去报文头字段
                //param.put("retMsg", IcbcExpayConstants.getRetMsg(res.getEb().getOut().getResult()));
                param.put("retMsg", res.getReturnInfo());
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(false);
                result.setOrderFail(true);
                result.setBankRetCode(res.getBankRetCode());// 快捷API失败通知
            } else {
            	//工行快捷新增失败信息  add by wjq 2017/12/6
                String retMsg="交易失败";
                if(res == null){
                }else if("0".equals(res.getBankRetCode())){
                	retMsg=IcbcExpayConstants.getRetMsg(res.getEb().getOut().getResult());
                	result.setBankRetCode(res.getEb().getOut().getResult());
                }else{
                	retMsg=res.getReturnInfo();
                	result.setBankRetCode(res.getBankRetCode());
                }
                param.put("orderId", baseMsg.getOrderId());
                param.put("amt", baseMsg.getAmount().toString());
                param.put("cardType", "Unknown");
                param.put("notifyNum", "1");
                param.put("payStatus", "01");
                param.put("retCode", "01");
                param.put("retMsg", retMsg);
                param.put("isFront", String.valueOf(false));
                result.setModel("isNotifyCashier", param);
                result.setSuccess(true);
                result.setOrderStatus(false);
            }
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
			BankLogUtils.printServiceImplExceptionLog(ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6057);
		}
        return result;
    }
    
    @Override
    public Result sign(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result verify(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result treatyQuery(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result cancel(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    

    @Override
    public Result refund(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Result queryOrder(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        IcbcQueryExpayCmsReq message = new IcbcQueryExpayCmsReq();
        BeanUtils.copyProperties(baseMsg, message);
        try{
            IcbcQueryExpayCmsRes res = (IcbcQueryExpayCmsRes) icbcExPayManager.queryOrder(message);
            result.setDefaultModel(res);
            result.setSuccess(true);
            result.setBankRetCode(res.getBankRetCode());
        }catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        }catch (Exception ex) {
			BankLogUtils.printServiceImplExceptionLog(ex);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100E6058);
		}
        return result;
    }


    @Override
    public Result queryCvn(ExPayBaseMessage baseMsg) {
        Result result = new Result(false);
        result.setSuccess(true);
        result.setModel("flag", true);
        result.setModel("isQueryCVN", IcbcConstants.ICBC_EXPAY_NOTQUERYCVN);
        return result;
    }

    @Override
    public Result queryNeedCert(ExPayBaseMessage baseMsg) {
        // TODO Auto-generated method stub
        return null;
    }

    public SmsSupportController getSmsController() {
        return smsController;
    }

    public void setSmsController(SmsSupportController smsController) {
        this.smsController = smsController;
    }

	@Override
	public Result refundBack(ExPayBaseMessage baseMsg) {
		// TODO Auto-generated method stub
		return null;
	}

    
}
